iT邦幫忙

2023 iThome 鐵人賽

DAY 4
1
Software Development

Rust Web API 從零開始系列 第 4

Day04 - 先做一個health check吧

  • 分享至 

  • xImage
  •  

原本預計要介紹router的細部設定和middleware,但我決定改從專案的第一個 API 開始。

Health Check

選擇用health check當作開始是因為它足夠簡單,通常我們需要一些方法來確保應用程式正常運行,例如定期對網頁應用進行健康檢查,今天要做的事情是:

  1. 建立一個路徑為 /health_check 的API。
  2. 當收到 GET 請求時,簡單地回覆200的狀態碼。

所以我們把昨天hello world的範例改一下

use axum::{http::StatusCode, routing::get, Router};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/health_check", get(health_check));

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

pub async fn health_check() -> StatusCode {
    StatusCode::OK
}

存檔後在terminal中使用cargo run指令,等待編譯過後程式運行

❯ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.14s
     Running `target/debug/zero_to_production`

這時候在測試 http://localhost:3000/health_check 理論上就可以收到200的回覆了。

Handler

跟昨天的程式碼相比,可以看到一開始的參考多了http::StatusCode,這是因為health_check處理函數的回應會使用到StatusCode這個 Enum,我們把焦點放到health_check方法上:

pub async fn health_check() -> StatusCode {
    StatusCode::OK
}

這是一個非常簡單的處理函數,只需回應StatusCode::OK,這代表 HTTP 200 OK。當我們訪問/health_check時,只需確認服務正在運行,因此這樣的回應就足夠了。

在Rust中,Enum是一個常見的概念,就像其他語言中的Enum一樣,它用於列舉一組可能的值,C#中也有這樣一個Enum用來表示Http Status的各種不同狀態。但是Rust的Enum與其他語言有所不同,因為在Rust中,Enum的每個項目都可以具備不同的資料型態。更多關於Enum的內容將在後續介紹錯誤處理的章節中進行深入討論。

IntoResponse Trait

一個Handler的回傳型別必須實現IntoResponse trait,這個trait定義了如何將值轉換為HTTP回應。trait是rust中的一種抽象概念,這邊先不仔細探究,先把它當成C#中的interface即可。trait定義的了一組方法,通常情況下只定義了方法簽章而不包含實做細節,以下是IntoResponse的定義:

pub trait IntoResponse {
    // Required method
    fn into_response(self) -> Response<UnsyncBoxBody<Bytes, Error>>;
}

實作了IntoResponse的型別就具備了一個方法。在上述定義中,self表示這是一個關聯方法,也就是實作細節可能與型別本身的資料有關。該方法的返回值是一個Response結構,其他細節在此先忽略。通常情況下,實作這個 trait並沒有看起來的那麼複雜,因為Axum已經為一些常見的Response型別提供了實作,所以在實際使用時,只需定義如何轉換為內建的 Response 即可。

如同上面的程式碼,我們已經知道StatusCode有實做IntoResponse:

//// 定義自己的Response
struct MyResponse(String);

//// 為MyResponse實做IntoResponse trait
impl IntoResponse for MyResponse {
    fn into_response(self) -> axum::response::Response {
        if self.0 == "Hello, World!" {
            //// 這邊直接調用StatusCode的into_response即可
            StatusCode::OK.into_response()
        } else {
            StatusCode::BAD_REQUEST.into_response()
        }
    }
}

Axum中已經為多種型別實作了IntoResponse,包括StringVec<u8>Json<T>Html<&'static str>等。此外,Handler也可以直接回傳實作了IntoResponse的trait物件,還可以使用tuple包裝多個回應值,或者使用Rust常用於處裡錯誤的Result。更多細節可以參考文件,至於詳細使用方式就留到後面完成更多功能的時候細細體會吧!

小結

今天通過health_check接觸到了第一個trait,並說明如何簡單的實作IntoResponse,不過在rust中trait的概念還是太抽象了,所以明天在重新看一次這個流程深入了解


上一篇
Day03 - 淺談Axum
下一篇
Day05 - 從Server到Handler
系列文
Rust Web API 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言